{
 "metadata": {
  "kernelspec": {
   "name": "python3",
   "display_name": "Python 3",
   "language": "python"
  },
  "language_info": {
   "name": "python",
   "version": "3.10.12",
   "mimetype": "text/x-python",
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "pygments_lexer": "ipython3",
   "nbconvert_exporter": "python",
   "file_extension": ".py"
  },
  "kaggle": {
   "accelerator": "gpu",
   "dataSources": [
    {
     "sourceId": 3649,
     "databundleVersionId": 46718,
     "sourceType": "competition"
    }
   ],
   "dockerImageVersionId": 30588,
   "isInternetEnabled": true,
   "language": "python",
   "sourceType": "notebook",
   "isGpuEnabled": true
  }
 },
 "nbformat_minor": 4,
 "nbformat": 4,
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "<font color=\"red\">注</font>: 使用 tensorboard 可视化需要安装 tensorflow (TensorBoard依赖于tensorflow库，可以任意安装tensorflow的gpu/cpu版本)\n",
    "\n",
    "```shell\n",
    "pip install tensorflow-cpu\n",
    "```"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "source": [
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import sklearn\n",
    "import pandas as pd\n",
    "import os\n",
    "import sys\n",
    "import time\n",
    "from tqdm.auto import tqdm\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "print(sys.version_info)\n",
    "for module in mpl, np, pd, sklearn, torch:\n",
    "    print(module.__name__, module.__version__)\n",
    "    \n",
    "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
    "print(device)\n",
    "\n",
    "seed = 42\n"
   ],
   "metadata": {
    "execution": {
     "iopub.status.busy": "2023-12-06T07:08:48.176838Z",
     "iopub.execute_input": "2023-12-06T07:08:48.177692Z",
     "iopub.status.idle": "2023-12-06T07:08:52.173245Z",
     "shell.execute_reply.started": "2023-12-06T07:08:48.177656Z",
     "shell.execute_reply": "2023-12-06T07:08:52.172296Z"
    },
    "trusted": true,
    "ExecuteTime": {
     "end_time": "2024-07-23T08:27:38.595781600Z",
     "start_time": "2024-07-23T08:27:30.267975300Z"
    }
   },
   "execution_count": 1,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sys.version_info(major=3, minor=12, micro=3, releaselevel='final', serial=0)\n",
      "matplotlib 3.9.0\n",
      "numpy 1.26.4\n",
      "pandas 2.2.2\n",
      "sklearn 1.5.0\n",
      "torch 2.3.1+cpu\n",
      "cpu\n"
     ]
    }
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 数据准备\n",
    "\n",
    "https://www.kaggle.com/competitions/cifar-10/data\n",
    "\n",
    "```shell\n",
    "$ tree -L 1 cifar-10                                    \n",
    "cifar-10\n",
    "├── sampleSubmission.csv\n",
    "├── test\n",
    "├── train\n",
    "└── trainLabels.csv\n",
    "```"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "source": [
    "%pip install py7zr\n",
    "import py7zr\n",
    "a = py7zr.SevenZipFile(r'../input/cifar-10/train.7z','r')\n",
    "a.extractall(path=r'./')\n",
    "a.close()"
   ],
   "metadata": {
    "execution": {
     "iopub.status.busy": "2023-12-06T07:08:52.174959Z",
     "iopub.execute_input": "2023-12-06T07:08:52.175398Z",
     "iopub.status.idle": "2023-12-06T07:10:04.178720Z",
     "shell.execute_reply.started": "2023-12-06T07:08:52.175370Z",
     "shell.execute_reply": "2023-12-06T07:10:04.177696Z"
    },
    "trusted": true
   },
   "execution_count": 2,
   "outputs": [
    {
     "name": "stdout",
     "text": "Collecting py7zr\n  Obtaining dependency information for py7zr from https://files.pythonhosted.org/packages/c0/39/71263be4c6081e1788f4da35e937fca1808914b0d98a04bd44255b948699/py7zr-0.20.8-py3-none-any.whl.metadata\n  Downloading py7zr-0.20.8-py3-none-any.whl.metadata (16 kB)\nRequirement already satisfied: texttable in /opt/conda/lib/python3.10/site-packages (from py7zr) (1.7.0)\nCollecting pycryptodomex>=3.16.0 (from py7zr)\n  Obtaining dependency information for pycryptodomex>=3.16.0 from https://files.pythonhosted.org/packages/23/23/3f3d042c96ff7bece5b126365593b1f9c8e3ae62ce80d44e9da39c5e8a73/pycryptodomex-3.19.0-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata\n  Downloading pycryptodomex-3.19.0-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (3.4 kB)\nCollecting pyzstd>=0.15.9 (from py7zr)\n  Obtaining dependency information for pyzstd>=0.15.9 from https://files.pythonhosted.org/packages/02/97/57de14ccb0d033464aabc5110eb2f9dc717c97e17f2ffc1235680a27e5de/pyzstd-0.15.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata\n  Downloading pyzstd-0.15.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (7.5 kB)\nCollecting pyppmd<1.2.0,>=1.1.0 (from py7zr)\n  Obtaining dependency information for pyppmd<1.2.0,>=1.1.0 from https://files.pythonhosted.org/packages/09/76/61db4268a439cfba8736b14130d928d199633fab2360a2c5043332a427d2/pyppmd-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata\n  Downloading pyppmd-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (5.7 kB)\nCollecting pybcj<1.1.0,>=1.0.0 (from py7zr)\n  Obtaining dependency information for pybcj<1.1.0,>=1.0.0 from https://files.pythonhosted.org/packages/09/70/8b6a6cc2a5721f67f629bdc17875c0d603d57f360a19b099a7b4de19383d/pybcj-1.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata\n  Downloading pybcj-1.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (4.0 kB)\nCollecting multivolumefile>=0.2.3 (from py7zr)\n  Downloading multivolumefile-0.2.3-py3-none-any.whl (17 kB)\nCollecting inflate64<1.1.0,>=1.0.0 (from py7zr)\n  Obtaining dependency information for inflate64<1.1.0,>=1.0.0 from https://files.pythonhosted.org/packages/b8/f4/e387a50f5027194eac4f9712d57b97e3e1a012402eaae98bcf1ebe8a97d1/inflate64-1.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata\n  Downloading inflate64-1.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (4.0 kB)\nCollecting brotli>=1.1.0 (from py7zr)\n  Obtaining dependency information for brotli>=1.1.0 from https://files.pythonhosted.org/packages/d5/00/40f760cc27007912b327fe15bf6bfd8eaecbe451687f72a8abc587d503b3/Brotli-1.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl.metadata\n  Downloading Brotli-1.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl.metadata (5.5 kB)\nRequirement already satisfied: psutil in /opt/conda/lib/python3.10/site-packages (from py7zr) (5.9.3)\nDownloading py7zr-0.20.8-py3-none-any.whl (67 kB)\n\u001B[2K   \u001B[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001B[0m \u001B[32m67.0/67.0 kB\u001B[0m \u001B[31m7.7 MB/s\u001B[0m eta \u001B[36m0:00:00\u001B[0m\n\u001B[?25hDownloading Brotli-1.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (3.0 MB)\n\u001B[2K   \u001B[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001B[0m \u001B[32m3.0/3.0 MB\u001B[0m \u001B[31m71.1 MB/s\u001B[0m eta \u001B[36m0:00:00\u001B[0m:00:01\u001B[0m\n\u001B[?25hDownloading inflate64-1.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (93 kB)\n\u001B[2K   \u001B[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001B[0m \u001B[32m93.1/93.1 kB\u001B[0m \u001B[31m9.9 MB/s\u001B[0m eta \u001B[36m0:00:00\u001B[0m\n\u001B[?25hDownloading pybcj-1.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (49 kB)\n\u001B[2K   \u001B[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001B[0m \u001B[32m49.7/49.7 kB\u001B[0m \u001B[31m5.0 MB/s\u001B[0m eta \u001B[36m0:00:00\u001B[0m\n\u001B[?25hDownloading pycryptodomex-3.19.0-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.1 MB)\n\u001B[2K   \u001B[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001B[0m \u001B[32m2.1/2.1 MB\u001B[0m \u001B[31m83.1 MB/s\u001B[0m eta \u001B[36m0:00:00\u001B[0m\n\u001B[?25hDownloading pyppmd-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (138 kB)\n\u001B[2K   \u001B[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001B[0m \u001B[32m138.9/138.9 kB\u001B[0m \u001B[31m17.0 MB/s\u001B[0m eta \u001B[36m0:00:00\u001B[0m\n\u001B[?25hDownloading pyzstd-0.15.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (412 kB)\n\u001B[2K   \u001B[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001B[0m \u001B[32m412.3/412.3 kB\u001B[0m \u001B[31m36.0 MB/s\u001B[0m eta \u001B[36m0:00:00\u001B[0m\n\u001B[?25hInstalling collected packages: brotli, pyzstd, pyppmd, pycryptodomex, pybcj, multivolumefile, inflate64, py7zr\nSuccessfully installed brotli-1.1.0 inflate64-1.0.0 multivolumefile-0.2.3 py7zr-0.20.8 pybcj-1.0.2 pycryptodomex-3.19.0 pyppmd-1.1.0 pyzstd-0.15.9\nNote: you may need to restart the kernel to use updated packages.\n",
     "output_type": "stream"
    }
   ]
  },
  {
   "cell_type": "code",
   "source": [
    "#我们不运行test数据集，太多图片\n",
    "!ls ."
   ],
   "metadata": {
    "execution": {
     "iopub.status.busy": "2023-12-06T07:13:10.875887Z",
     "iopub.execute_input": "2023-12-06T07:13:10.876737Z",
     "iopub.status.idle": "2023-12-06T07:13:11.853398Z",
     "shell.execute_reply.started": "2023-12-06T07:13:10.876700Z",
     "shell.execute_reply": "2023-12-06T07:13:11.852424Z"
    },
    "trusted": true
   },
   "execution_count": 17,
   "outputs": [
    {
     "name": "stdout",
     "text": "checkpoints  runs  train\n",
     "output_type": "stream"
    }
   ]
  },
  {
   "cell_type": "code",
   "source": [
    "!mkdir test"
   ],
   "metadata": {
    "execution": {
     "iopub.status.busy": "2023-12-06T07:13:28.479278Z",
     "iopub.execute_input": "2023-12-06T07:13:28.480244Z",
     "iopub.status.idle": "2023-12-06T07:13:29.465017Z",
     "shell.execute_reply.started": "2023-12-06T07:13:28.480203Z",
     "shell.execute_reply": "2023-12-06T07:13:29.463640Z"
    },
    "trusted": true
   },
   "execution_count": 18,
   "outputs": []
  },
  {
   "cell_type": "code",
   "source": [
    "!cp ../input/cifar-10/*.csv . -r"
   ],
   "metadata": {
    "execution": {
     "iopub.status.busy": "2023-12-06T07:14:25.805019Z",
     "iopub.execute_input": "2023-12-06T07:14:25.805362Z",
     "iopub.status.idle": "2023-12-06T07:14:26.795890Z",
     "shell.execute_reply.started": "2023-12-06T07:14:25.805335Z",
     "shell.execute_reply": "2023-12-06T07:14:26.794507Z"
    },
    "trusted": true
   },
   "execution_count": 20,
   "outputs": []
  },
  {
   "cell_type": "code",
   "source": [
    "from pathlib import Path\n",
    "\n",
    "DATA_DIR = Path(\"D:\\cifar-10\")\n",
    "\n",
    "train_lables_file = DATA_DIR / \"trainLabels.csv\"\n",
    "test_csv_file = DATA_DIR / \"sampleSubmission.csv\"\n",
    "train_folder = DATA_DIR / \"train/\"\n",
    "test_folder = DATA_DIR / \"test\"\n",
    "\n",
    "#所有的类别\n",
    "class_names = [\n",
    "    'airplane',\n",
    "    'automobile',\n",
    "    'bird',\n",
    "    'cat',\n",
    "    'deer',\n",
    "    'dog',\n",
    "    'frog',\n",
    "    'horse',\n",
    "    'ship',\n",
    "    'truck',\n",
    "]\n",
    "\n",
    "def parse_csv_file(filepath, folder):\n",
    "    \"\"\"Parses csv files into (filename(path), label) format\"\"\"\n",
    "    results = []\n",
    "    #读取所有行\n",
    "    with open(filepath, 'r') as f:\n",
    "#         lines = f.readlines()  为什么加[1:]，可以试这个\n",
    "        #第一行不需要，因为第一行是标签\n",
    "        lines = f.readlines()[1:] \n",
    "    for line in lines:#依次去取每一行\n",
    "        image_id, label_str = line.strip('\\n').split(',')\n",
    "        image_full_path = folder / f\"{image_id}.png\"\n",
    "        results.append((image_full_path, label_str)) #得到对应图片的路径和分类\n",
    "    return results\n",
    "\n",
    "#解析对应的文件夹\n",
    "train_labels_info = parse_csv_file(train_lables_file, train_folder)\n",
    "test_csv_info = parse_csv_file(test_csv_file, test_folder)\n",
    "#打印\n",
    "import pprint\n",
    "pprint.pprint(train_labels_info[0:5])\n",
    "pprint.pprint(test_csv_info[0:5])\n",
    "print(len(train_labels_info), len(test_csv_info))"
   ],
   "metadata": {
    "execution": {
     "iopub.status.busy": "2023-12-06T07:14:26.798639Z",
     "iopub.execute_input": "2023-12-06T07:14:26.799055Z",
     "iopub.status.idle": "2023-12-06T07:14:50.396034Z",
     "shell.execute_reply.started": "2023-12-06T07:14:26.799017Z",
     "shell.execute_reply": "2023-12-06T07:14:50.395100Z"
    },
    "trusted": true,
    "ExecuteTime": {
     "end_time": "2024-07-23T08:31:32.703456Z",
     "start_time": "2024-07-23T08:31:29.807018300Z"
    }
   },
   "execution_count": 3,
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "<>:3: SyntaxWarning: invalid escape sequence '\\c'\n",
      "<>:3: SyntaxWarning: invalid escape sequence '\\c'\n",
      "C:\\Users\\Administrator\\AppData\\Local\\Temp\\ipykernel_8900\\580068613.py:3: SyntaxWarning: invalid escape sequence '\\c'\n",
      "  DATA_DIR = Path(\"D:\\cifar-10\")\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(WindowsPath('D:/cifar-10/train/1.png'), 'frog'),\n",
      " (WindowsPath('D:/cifar-10/train/2.png'), 'truck'),\n",
      " (WindowsPath('D:/cifar-10/train/3.png'), 'truck'),\n",
      " (WindowsPath('D:/cifar-10/train/4.png'), 'deer'),\n",
      " (WindowsPath('D:/cifar-10/train/5.png'), 'automobile')]\n",
      "[(WindowsPath('D:/cifar-10/test/1.png'), 'cat'),\n",
      " (WindowsPath('D:/cifar-10/test/2.png'), 'cat'),\n",
      " (WindowsPath('D:/cifar-10/test/3.png'), 'cat'),\n",
      " (WindowsPath('D:/cifar-10/test/4.png'), 'cat'),\n",
      " (WindowsPath('D:/cifar-10/test/5.png'), 'cat')]\n",
      "50000 300000\n"
     ]
    }
   ]
  },
  {
   "cell_type": "code",
   "source": [
    "# train_df = pd.DataFrame(train_labels_info)\n",
    "train_df = pd.DataFrame(train_labels_info[0:45000])\n",
    "valid_df = pd.DataFrame(train_labels_info[45000:])\n",
    "test_df = pd.DataFrame(test_csv_info)\n",
    "\n",
    "train_df.columns = ['filepath', 'class']\n",
    "valid_df.columns = ['filepath', 'class']\n",
    "test_df.columns = ['filepath', 'class']\n",
    "\n",
    "print(train_df.head())\n",
    "print(valid_df.head())\n",
    "print(test_df.head())"
   ],
   "metadata": {
    "execution": {
     "iopub.status.busy": "2023-12-06T07:14:50.397500Z",
     "iopub.execute_input": "2023-12-06T07:14:50.397872Z",
     "iopub.status.idle": "2023-12-06T07:14:50.504483Z",
     "shell.execute_reply.started": "2023-12-06T07:14:50.397838Z",
     "shell.execute_reply": "2023-12-06T07:14:50.503554Z"
    },
    "trusted": true,
    "ExecuteTime": {
     "end_time": "2024-04-29T03:02:56.392950700Z",
     "start_time": "2024-04-29T03:02:56.258029400Z"
    }
   },
   "execution_count": 5,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "                  filepath       class\n",
      "0  D:\\cifar-10\\train\\1.png        frog\n",
      "1  D:\\cifar-10\\train\\2.png       truck\n",
      "2  D:\\cifar-10\\train\\3.png       truck\n",
      "3  D:\\cifar-10\\train\\4.png        deer\n",
      "4  D:\\cifar-10\\train\\5.png  automobile\n",
      "                      filepath       class\n",
      "0  D:\\cifar-10\\train\\45001.png       horse\n",
      "1  D:\\cifar-10\\train\\45002.png  automobile\n",
      "2  D:\\cifar-10\\train\\45003.png        deer\n",
      "3  D:\\cifar-10\\train\\45004.png  automobile\n",
      "4  D:\\cifar-10\\train\\45005.png    airplane\n",
      "                 filepath class\n",
      "0  D:\\cifar-10\\test\\1.png   cat\n",
      "1  D:\\cifar-10\\test\\2.png   cat\n",
      "2  D:\\cifar-10\\test\\3.png   cat\n",
      "3  D:\\cifar-10\\test\\4.png   cat\n",
      "4  D:\\cifar-10\\test\\5.png   cat\n"
     ]
    }
   ]
  },
  {
   "cell_type": "code",
   "source": [
    "from PIL import Image\n",
    "from torch.utils.data import Dataset, DataLoader\n",
    "from torchvision import transforms\n",
    "\n",
    "class Cifar10Dataset(Dataset):\n",
    "    df_map = {\n",
    "        \"train\": train_df,\n",
    "        \"eval\": valid_df,\n",
    "        \"test\": test_df\n",
    "    }\n",
    "    label_to_idx = {label: idx for idx, label in enumerate(class_names)}\n",
    "    idx_to_label = {idx: label for idx, label in enumerate(class_names)}\n",
    "    def __init__(self, mode, transform=None):\n",
    "        self.df = self.df_map.get(mode, None)\n",
    "        if self.df is None:\n",
    "            raise ValueError(\"mode should be one of train, val, test, but got {}\".format(mode))\n",
    "\n",
    "        self.transform = transform\n",
    "        \n",
    "    def __getitem__(self, index):\n",
    "        img_path, label = self.df.iloc[index]\n",
    "        img = Image.open(img_path).convert('RGB')\n",
    "        # # img 转换为 channel first\n",
    "        # img = img.transpose((2, 0, 1))\n",
    "        # transform\n",
    "        img = self.transform(img)\n",
    "        # label 转换为 idx\n",
    "        label = self.label_to_idx[label]\n",
    "        return img, label\n",
    "    \n",
    "    def __len__(self):\n",
    "        return self.df.shape[0]\n",
    "    \n",
    "IMAGE_SIZE = 32\n",
    "mean, std = [0.4914, 0.4822, 0.4465], [0.247, 0.243, 0.261]\n",
    "\n",
    "transforms_train = transforms.Compose([\n",
    "        # resize\n",
    "        transforms.Resize((IMAGE_SIZE, IMAGE_SIZE)),\n",
    "        # random rotation 40\n",
    "        transforms.RandomRotation(40),\n",
    "        # horizaontal flip\n",
    "        transforms.RandomHorizontalFlip(),\n",
    "        transforms.ToTensor(),\n",
    "        transforms.Normalize(mean, std)\n",
    "    ])\n",
    "\n",
    "transforms_eval = transforms.Compose([\n",
    "        # resize\n",
    "        transforms.Resize((IMAGE_SIZE, IMAGE_SIZE)),\n",
    "        transforms.ToTensor(),\n",
    "        transforms.Normalize(mean, std)\n",
    "    ])\n",
    "\n",
    "train_ds = Cifar10Dataset(\"train\", transforms_train)\n",
    "eval_ds = Cifar10Dataset(\"eval\", transforms_eval) "
   ],
   "metadata": {
    "execution": {
     "iopub.status.busy": "2023-12-06T07:14:50.506929Z",
     "iopub.execute_input": "2023-12-06T07:14:50.507246Z",
     "iopub.status.idle": "2023-12-06T07:14:50.519122Z",
     "shell.execute_reply.started": "2023-12-06T07:14:50.507220Z",
     "shell.execute_reply": "2023-12-06T07:14:50.518245Z"
    },
    "trusted": true,
    "ExecuteTime": {
     "end_time": "2024-04-29T03:03:03.848298800Z",
     "start_time": "2024-04-29T03:03:00.932067300Z"
    }
   },
   "execution_count": 6,
   "outputs": []
  },
  {
   "cell_type": "code",
   "source": [
    "batch_size = 64\n",
    "train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True, num_workers=4)   \n",
    "eval_dl = DataLoader(eval_ds, batch_size=batch_size, shuffle=False, num_workers=4)"
   ],
   "metadata": {
    "execution": {
     "iopub.status.busy": "2023-12-06T07:14:50.520317Z",
     "iopub.execute_input": "2023-12-06T07:14:50.520683Z",
     "iopub.status.idle": "2023-12-06T07:14:50.532468Z",
     "shell.execute_reply.started": "2023-12-06T07:14:50.520651Z",
     "shell.execute_reply": "2023-12-06T07:14:50.531594Z"
    },
    "trusted": true,
    "ExecuteTime": {
     "end_time": "2024-04-29T03:03:05.314368700Z",
     "start_time": "2024-04-29T03:03:05.306373600Z"
    }
   },
   "execution_count": 7,
   "outputs": []
  },
  {
   "cell_type": "code",
   "source": [
    "# 遍历train_ds得到每张图片，计算每个通道的均值和方差\n",
    "#这里不需要每次都执行，只需要执行一次就可以了，所以注释掉\n",
    "# def cal_mean_std(ds):\n",
    "#     mean = 0.\n",
    "#     std = 0.\n",
    "#     for img, _ in ds:\n",
    "#         mean += img.mean(dim=(1, 2))\n",
    "#         std += img.std(dim=(1, 2))\n",
    "#     mean /= len(ds)\n",
    "#     std /= len(ds)\n",
    "#     return mean, std\n",
    "#\n",
    "# # 经过 normalize 后 均值为0，方差为1\n",
    "# print(cal_mean_std(train_ds))"
   ],
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-12-05T09:51:19.396136500Z",
     "start_time": "2023-12-05T09:46:43.935044500Z"
    },
    "execution": {
     "iopub.status.busy": "2023-12-06T07:14:50.533728Z",
     "iopub.execute_input": "2023-12-06T07:14:50.534185Z",
     "iopub.status.idle": "2023-12-06T07:14:50.542199Z",
     "shell.execute_reply.started": "2023-12-06T07:14:50.534154Z",
     "shell.execute_reply": "2023-12-06T07:14:50.541519Z"
    },
    "trusted": true
   },
   "execution_count": 25,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 定义模型"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "source": [
    "class VGG(nn.Module):\n",
    "    def __init__(self, num_classes):\n",
    "        super().__init__()\n",
    "        self.model = nn.Sequential(\n",
    "            nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, padding=\"same\"),\n",
    "            nn.ReLU(),\n",
    "            nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, padding=\"same\"),\n",
    "            nn.ReLU(),\n",
    "            nn.MaxPool2d(kernel_size=2),\n",
    "            nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, padding=\"same\"),\n",
    "            nn.ReLU(),\n",
    "            nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, padding=\"same\"),\n",
    "            nn.ReLU(),\n",
    "            nn.MaxPool2d(kernel_size=2),\n",
    "            nn.Conv2d(in_channels=128, out_channels=256, kernel_size=3, padding=\"same\"),\n",
    "            nn.ReLU(),\n",
    "            nn.Conv2d(in_channels=256, out_channels=256, kernel_size=3, padding=\"same\"),\n",
    "            nn.ReLU(),\n",
    "            nn.Conv2d(in_channels=256, out_channels=256, kernel_size=3, padding=\"same\"),\n",
    "            nn.ReLU(),\n",
    "            nn.Conv2d(in_channels=256, out_channels=256, kernel_size=3, padding=\"same\"),\n",
    "            nn.ReLU(),\n",
    "            nn.MaxPool2d(kernel_size=2),\n",
    "            #下一个512\n",
    "            nn.Conv2d(in_channels=256, out_channels=512, kernel_size=3, padding=\"same\"),\n",
    "            nn.ReLU(),\n",
    "            nn.Conv2d(in_channels=512, out_channels=512, kernel_size=3, padding=\"same\"),\n",
    "            nn.ReLU(),\n",
    "            nn.Conv2d(in_channels=512, out_channels=512, kernel_size=3, padding=\"same\"),\n",
    "            nn.ReLU(),\n",
    "            nn.Conv2d(in_channels=512, out_channels=512, kernel_size=3, padding=\"same\"),\n",
    "            nn.ReLU(),\n",
    "            nn.MaxPool2d(kernel_size=2),\n",
    "            #下一个512\n",
    "            nn.Conv2d(in_channels=512, out_channels=512, kernel_size=3, padding=\"same\"),\n",
    "            nn.ReLU(),\n",
    "            nn.Conv2d(in_channels=512, out_channels=512, kernel_size=3, padding=\"same\"),\n",
    "            nn.ReLU(),\n",
    "            nn.Conv2d(in_channels=512, out_channels=512, kernel_size=3, padding=\"same\"),\n",
    "            nn.ReLU(),\n",
    "            nn.Conv2d(in_channels=512, out_channels=512, kernel_size=3, padding=\"same\"),\n",
    "            nn.ReLU(),\n",
    "            nn.MaxPool2d(kernel_size=2),\n",
    "            nn.Flatten(),\n",
    "            nn.Linear(512, num_classes),\n",
    "        )\n",
    "        self.init_weights()\n",
    "        \n",
    "    def init_weights(self):\n",
    "        \"\"\"使用 xavier 均匀分布来初始化全连接层、卷积层的权重 W\"\"\"\n",
    "        for m in self.modules():\n",
    "            if isinstance(m, (nn.Linear, nn.Conv2d)):\n",
    "                nn.init.xavier_uniform_(m.weight)\n",
    "                nn.init.zeros_(m.bias)\n",
    "        \n",
    "    def forward(self, x):\n",
    "        return self.model(x)\n",
    "        \n",
    "for key, value in VGG(len(class_names)).named_parameters():\n",
    "    print(f\"{key:^40}paramerters num: {np.prod(value.shape)}\")\n",
    "    \n"
   ],
   "metadata": {
    "execution": {
     "iopub.status.busy": "2023-12-06T07:14:50.543362Z",
     "iopub.execute_input": "2023-12-06T07:14:50.543636Z",
     "iopub.status.idle": "2023-12-06T07:14:50.559521Z",
     "shell.execute_reply.started": "2023-12-06T07:14:50.543613Z",
     "shell.execute_reply": "2023-12-06T07:14:50.558524Z"
    },
    "trusted": true,
    "ExecuteTime": {
     "end_time": "2024-07-23T08:31:41.478343100Z",
     "start_time": "2024-07-23T08:31:41.137983400Z"
    }
   },
   "execution_count": 4,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "             model.0.weight             paramerters num: 1728\n",
      "              model.0.bias              paramerters num: 64\n",
      "             model.2.weight             paramerters num: 36864\n",
      "              model.2.bias              paramerters num: 64\n",
      "             model.5.weight             paramerters num: 73728\n",
      "              model.5.bias              paramerters num: 128\n",
      "             model.7.weight             paramerters num: 147456\n",
      "              model.7.bias              paramerters num: 128\n",
      "            model.10.weight             paramerters num: 294912\n",
      "             model.10.bias              paramerters num: 256\n",
      "            model.12.weight             paramerters num: 589824\n",
      "             model.12.bias              paramerters num: 256\n",
      "            model.14.weight             paramerters num: 589824\n",
      "             model.14.bias              paramerters num: 256\n",
      "            model.16.weight             paramerters num: 589824\n",
      "             model.16.bias              paramerters num: 256\n",
      "            model.19.weight             paramerters num: 1179648\n",
      "             model.19.bias              paramerters num: 512\n",
      "            model.21.weight             paramerters num: 2359296\n",
      "             model.21.bias              paramerters num: 512\n",
      "            model.23.weight             paramerters num: 2359296\n",
      "             model.23.bias              paramerters num: 512\n",
      "            model.25.weight             paramerters num: 2359296\n",
      "             model.25.bias              paramerters num: 512\n",
      "            model.28.weight             paramerters num: 2359296\n",
      "             model.28.bias              paramerters num: 512\n",
      "            model.30.weight             paramerters num: 2359296\n",
      "             model.30.bias              paramerters num: 512\n",
      "            model.32.weight             paramerters num: 2359296\n",
      "             model.32.bias              paramerters num: 512\n",
      "            model.34.weight             paramerters num: 2359296\n",
      "             model.34.bias              paramerters num: 512\n",
      "            model.38.weight             paramerters num: 5120\n",
      "             model.38.bias              paramerters num: 10\n"
     ]
    }
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "\n",
    "## 训练\n",
    "\n",
    "pytorch的训练需要自行实现，包括\n",
    "1. 定义损失函数\n",
    "2. 定义优化器\n",
    "3. 定义训练步\n",
    "4. 训练"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Total trainable parameters: 20029514\n"
     ]
    }
   ],
   "source": [
    "#模型总参数量\n",
    "total_params = sum(p.numel() for p in VGG(len(class_names)).parameters() if p.requires_grad)\n",
    "print(f\"Total trainable parameters: {total_params}\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-07-23T08:31:45.716963800Z",
     "start_time": "2024-07-23T08:31:45.415794300Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "outputs": [
    {
     "data": {
      "text/plain": "tensor([[ 3.9566e-04,  6.1541e-04, -1.2969e-04,  2.1759e-04,  3.2853e-04,\n          7.2515e-04,  2.1032e-04,  4.7057e-04,  5.7051e-05, -6.8711e-04]],\n       grad_fn=<AddmmBackward0>)"
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model = VGG(10)\n",
    "# model.to(device)\n",
    "img = torch.randn(1, 3, 32, 32)\n",
    "model(img)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-04-29T03:05:17.640265100Z",
     "start_time": "2024-04-29T03:05:16.110503400Z"
    }
   }
  },
  {
   "cell_type": "code",
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "@torch.no_grad()\n",
    "def evaluating(model, dataloader, loss_fct):\n",
    "    loss_list = []\n",
    "    pred_list = []\n",
    "    label_list = []\n",
    "    for datas, labels in dataloader:\n",
    "        datas = datas.to(device)\n",
    "        labels = labels.to(device)\n",
    "        # 前向计算\n",
    "        logits = model(datas)\n",
    "        loss = loss_fct(logits, labels)         # 验证集损失\n",
    "        loss_list.append(loss.item())\n",
    "        \n",
    "        preds = logits.argmax(axis=-1)    # 验证集预测\n",
    "        pred_list.extend(preds.cpu().numpy().tolist())\n",
    "        label_list.extend(labels.cpu().numpy().tolist())\n",
    "        \n",
    "    acc = accuracy_score(label_list, pred_list)\n",
    "    return np.mean(loss_list), acc\n"
   ],
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-12-05T09:51:19.650361500Z",
     "start_time": "2023-12-05T09:51:19.432189700Z"
    },
    "execution": {
     "iopub.status.busy": "2023-12-06T07:14:50.560695Z",
     "iopub.execute_input": "2023-12-06T07:14:50.560988Z",
     "iopub.status.idle": "2023-12-06T07:14:50.568396Z",
     "shell.execute_reply.started": "2023-12-06T07:14:50.560941Z",
     "shell.execute_reply": "2023-12-06T07:14:50.567498Z"
    },
    "trusted": true
   },
   "execution_count": 27,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "source": [
    "### TensorBoard 可视化\n",
    "\n",
    "\n",
    "训练过程中可以使用如下命令启动tensorboard服务。\n",
    "\n",
    "```shell\n",
    "tensorboard \\\n",
    "    --logdir=runs \\     # log 存放路径\n",
    "    --host 0.0.0.0 \\    # ip\n",
    "    --port 8848         # 端口\n",
    "```"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "source": [
    "from torch.utils.tensorboard import SummaryWriter\n",
    "\n",
    "\n",
    "class TensorBoardCallback:\n",
    "    def __init__(self, log_dir, flush_secs=10):\n",
    "        \"\"\"\n",
    "        Args:\n",
    "            log_dir (str): dir to write log.\n",
    "            flush_secs (int, optional): write to dsk each flush_secs seconds. Defaults to 10.\n",
    "        \"\"\"\n",
    "        self.writer = SummaryWriter(log_dir=log_dir, flush_secs=flush_secs)\n",
    "\n",
    "    def draw_model(self, model, input_shape):\n",
    "        self.writer.add_graph(model, input_to_model=torch.randn(input_shape))\n",
    "        \n",
    "    def add_loss_scalars(self, step, loss, val_loss):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/loss\", \n",
    "            tag_scalar_dict={\"loss\": loss, \"val_loss\": val_loss},\n",
    "            global_step=step,\n",
    "            )\n",
    "        \n",
    "    def add_acc_scalars(self, step, acc, val_acc):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/accuracy\",\n",
    "            tag_scalar_dict={\"accuracy\": acc, \"val_accuracy\": val_acc},\n",
    "            global_step=step,\n",
    "        )\n",
    "        \n",
    "    def add_lr_scalars(self, step, learning_rate):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/learning_rate\",\n",
    "            tag_scalar_dict={\"learning_rate\": learning_rate},\n",
    "            global_step=step,\n",
    "            \n",
    "        )\n",
    "    \n",
    "    def __call__(self, step, **kwargs):\n",
    "        # add loss\n",
    "        loss = kwargs.pop(\"loss\", None)\n",
    "        val_loss = kwargs.pop(\"val_loss\", None)\n",
    "        if loss is not None and val_loss is not None:\n",
    "            self.add_loss_scalars(step, loss, val_loss)\n",
    "        # add acc\n",
    "        acc = kwargs.pop(\"acc\", None)\n",
    "        val_acc = kwargs.pop(\"val_acc\", None)\n",
    "        if acc is not None and val_acc is not None:\n",
    "            self.add_acc_scalars(step, acc, val_acc)\n",
    "        # add lr\n",
    "        learning_rate = kwargs.pop(\"lr\", None)\n",
    "        if learning_rate is not None:\n",
    "            self.add_lr_scalars(step, learning_rate)\n"
   ],
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-12-05T09:51:26.334347900Z",
     "start_time": "2023-12-05T09:51:19.656342Z"
    },
    "execution": {
     "iopub.status.busy": "2023-12-06T07:14:50.569496Z",
     "iopub.execute_input": "2023-12-06T07:14:50.569784Z",
     "iopub.status.idle": "2023-12-06T07:14:50.582405Z",
     "shell.execute_reply.started": "2023-12-06T07:14:50.569753Z",
     "shell.execute_reply": "2023-12-06T07:14:50.581651Z"
    },
    "trusted": true
   },
   "execution_count": 28,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "source": [
    "### Save Best\n"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "source": [
    "class SaveCheckpointsCallback:\n",
    "    def __init__(self, save_dir, save_step=5000, save_best_only=True):\n",
    "        \"\"\"\n",
    "        Save checkpoints each save_epoch epoch. \n",
    "        We save checkpoint by epoch in this implementation.\n",
    "        Usually, training scripts with pytorch evaluating model and save checkpoint by step.\n",
    "\n",
    "        Args:\n",
    "            save_dir (str): dir to save checkpoint\n",
    "            save_epoch (int, optional): the frequency to save checkpoint. Defaults to 1.\n",
    "            save_best_only (bool, optional): If True, only save the best model or save each model at every epoch.\n",
    "        \"\"\"\n",
    "        self.save_dir = save_dir\n",
    "        self.save_step = save_step\n",
    "        self.save_best_only = save_best_only\n",
    "        self.best_metrics = -1\n",
    "        \n",
    "        # mkdir\n",
    "        if not os.path.exists(self.save_dir):\n",
    "            os.mkdir(self.save_dir)\n",
    "        \n",
    "    def __call__(self, step, state_dict, metric=None):\n",
    "        if step % self.save_step > 0:\n",
    "            return\n",
    "        \n",
    "        if self.save_best_only:\n",
    "            assert metric is not None\n",
    "            if metric >= self.best_metrics:\n",
    "                # save checkpoints\n",
    "                torch.save(state_dict, os.path.join(self.save_dir, \"best.ckpt\"))\n",
    "                # update best metrics\n",
    "                self.best_metrics = metric\n",
    "        else:\n",
    "            torch.save(state_dict, os.path.join(self.save_dir, f\"{step}.ckpt\"))\n",
    "\n"
   ],
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-12-05T09:51:26.347424300Z",
     "start_time": "2023-12-05T09:51:26.337347300Z"
    },
    "execution": {
     "iopub.status.busy": "2023-12-06T07:14:50.585385Z",
     "iopub.execute_input": "2023-12-06T07:14:50.585685Z",
     "iopub.status.idle": "2023-12-06T07:14:50.595564Z",
     "shell.execute_reply.started": "2023-12-06T07:14:50.585661Z",
     "shell.execute_reply": "2023-12-06T07:14:50.594812Z"
    },
    "trusted": true
   },
   "execution_count": 29,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "source": [
    "### Early Stop"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "source": [
    "class EarlyStopCallback:\n",
    "    def __init__(self, patience=5, min_delta=0.01):\n",
    "        \"\"\"\n",
    "\n",
    "        Args:\n",
    "            patience (int, optional): Number of epochs with no improvement after which training will be stopped.. Defaults to 5.\n",
    "            min_delta (float, optional): Minimum change in the monitored quantity to qualify as an improvement, i.e. an absolute \n",
    "                change of less than min_delta, will count as no improvement. Defaults to 0.01.\n",
    "        \"\"\"\n",
    "        self.patience = patience\n",
    "        self.min_delta = min_delta\n",
    "        self.best_metric = -1\n",
    "        self.counter = 0\n",
    "        \n",
    "    def __call__(self, metric):\n",
    "        if metric >= self.best_metric + self.min_delta:\n",
    "            # update best metric\n",
    "            self.best_metric = metric\n",
    "            # reset counter \n",
    "            self.counter = 0\n",
    "        else: \n",
    "            self.counter += 1\n",
    "            \n",
    "    @property\n",
    "    def early_stop(self):\n",
    "        return self.counter >= self.patience\n"
   ],
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-12-05T09:51:26.371402100Z",
     "start_time": "2023-12-05T09:51:26.351411800Z"
    },
    "execution": {
     "iopub.status.busy": "2023-12-06T07:14:50.596593Z",
     "iopub.execute_input": "2023-12-06T07:14:50.596972Z",
     "iopub.status.idle": "2023-12-06T07:14:50.608838Z",
     "shell.execute_reply.started": "2023-12-06T07:14:50.596928Z",
     "shell.execute_reply": "2023-12-06T07:14:50.608128Z"
    },
    "trusted": true
   },
   "execution_count": 30,
   "outputs": []
  },
  {
   "cell_type": "code",
   "source": [
    "# 训练\n",
    "def training(\n",
    "    model, \n",
    "    train_loader, \n",
    "    val_loader, \n",
    "    epoch, \n",
    "    loss_fct, \n",
    "    optimizer, \n",
    "    tensorboard_callback=None,\n",
    "    save_ckpt_callback=None,\n",
    "    early_stop_callback=None,\n",
    "    eval_step=500,\n",
    "    ):\n",
    "    record_dict = {\n",
    "        \"train\": [],\n",
    "        \"val\": []\n",
    "    }\n",
    "    \n",
    "    global_step = 0\n",
    "    model.train()\n",
    "    with tqdm(total=epoch * len(train_loader)) as pbar:\n",
    "        for epoch_id in range(epoch):\n",
    "            # training\n",
    "            for datas, labels in train_loader:\n",
    "                datas = datas.to(device)\n",
    "                labels = labels.to(device)\n",
    "                # 梯度清空\n",
    "                optimizer.zero_grad()\n",
    "                # 模型前向计算\n",
    "                logits = model(datas)\n",
    "                # 计算损失\n",
    "                loss = loss_fct(logits, labels)\n",
    "                # 梯度回传\n",
    "                loss.backward()\n",
    "                # 调整优化器，包括学习率的变动等\n",
    "                optimizer.step()\n",
    "                preds = logits.argmax(axis=-1)\n",
    "            \n",
    "                acc = accuracy_score(labels.cpu().numpy(), preds.cpu().numpy())    \n",
    "                loss = loss.cpu().item()\n",
    "                # record\n",
    "                \n",
    "                record_dict[\"train\"].append({\n",
    "                    \"loss\": loss, \"acc\": acc, \"step\": global_step\n",
    "                })\n",
    "                \n",
    "                # evaluating\n",
    "                if global_step % eval_step == 0:\n",
    "                    model.eval()\n",
    "                    val_loss, val_acc = evaluating(model, val_loader, loss_fct)\n",
    "                    record_dict[\"val\"].append({\n",
    "                        \"loss\": val_loss, \"acc\": val_acc, \"step\": global_step\n",
    "                    })\n",
    "                    model.train()\n",
    "                    \n",
    "                    # 1. 使用 tensorboard 可视化\n",
    "                    if tensorboard_callback is not None:\n",
    "                        tensorboard_callback(\n",
    "                            global_step, \n",
    "                            loss=loss, val_loss=val_loss,\n",
    "                            acc=acc, val_acc=val_acc,\n",
    "                            lr=optimizer.param_groups[0][\"lr\"],\n",
    "                            )\n",
    "                \n",
    "                    # 2. 保存模型权重 save model checkpoint\n",
    "                    if save_ckpt_callback is not None:\n",
    "                        save_ckpt_callback(global_step, model.state_dict(), metric=val_acc)\n",
    "\n",
    "                    # 3. 早停 Early Stop\n",
    "                    if early_stop_callback is not None:\n",
    "                        early_stop_callback(val_acc)\n",
    "                        if early_stop_callback.early_stop:\n",
    "                            print(f\"Early stop at epoch {epoch_id} / global_step {global_step}\")\n",
    "                            return record_dict\n",
    "                    \n",
    "                # udate step\n",
    "                global_step += 1\n",
    "                pbar.update(1)\n",
    "                pbar.set_postfix({\"epoch\": epoch_id})\n",
    "        \n",
    "    return record_dict\n",
    "        \n",
    "\n",
    "epoch = 10\n",
    "\n",
    "model = VGG(num_classes=10)\n",
    "\n",
    "# 1. 定义损失函数 采用交叉熵损失\n",
    "loss_fct = nn.CrossEntropyLoss()\n",
    "# 2. 定义优化器 采用 adam\n",
    "# Optimizers specified in the torch.optim package\n",
    "optimizer = torch.optim.Adam(model.parameters(), lr=0.001)\n",
    "\n",
    "# 1. tensorboard 可视化\n",
    "if not os.path.exists(\"runs\"):\n",
    "    os.mkdir(\"runs\")\n",
    "tensorboard_callback = TensorBoardCallback(\"runs/vgg\")\n",
    "tensorboard_callback.draw_model(model, [1, 3, IMAGE_SIZE, IMAGE_SIZE])\n",
    "# 2. save best\n",
    "if not os.path.exists(\"checkpoints\"):\n",
    "    os.makedirs(\"checkpoints\")\n",
    "save_ckpt_callback = SaveCheckpointsCallback(\"checkpoints/vgg\", save_step=len(train_dl), save_best_only=True)\n",
    "# 3. early stop\n",
    "early_stop_callback = EarlyStopCallback(patience=5)\n",
    "\n",
    "model = model.to(device)\n",
    "record = training(\n",
    "    model, \n",
    "    train_dl, \n",
    "    eval_dl, \n",
    "    epoch, \n",
    "    loss_fct, \n",
    "    optimizer, \n",
    "    tensorboard_callback=None,\n",
    "    save_ckpt_callback=save_ckpt_callback,\n",
    "    early_stop_callback=early_stop_callback,\n",
    "    eval_step=len(train_dl)\n",
    "    )"
   ],
   "metadata": {
    "is_executing": true,
    "ExecuteTime": {
     "start_time": "2023-12-05T09:51:26.364406400Z"
    },
    "execution": {
     "iopub.status.busy": "2023-12-06T07:14:50.610165Z",
     "iopub.execute_input": "2023-12-06T07:14:50.610652Z",
     "iopub.status.idle": "2023-12-06T07:17:50.070739Z",
     "shell.execute_reply.started": "2023-12-06T07:14:50.610620Z",
     "shell.execute_reply": "2023-12-06T07:17:50.069693Z"
    },
    "trusted": true
   },
   "execution_count": 31,
   "outputs": [
    {
     "output_type": "display_data",
     "data": {
      "text/plain": "  0%|          | 0/7040 [00:00<?, ?it/s]",
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "95d5af6b6df046b99626f4345a15d625"
      }
     },
     "metadata": {}
    }
   ]
  },
  {
   "cell_type": "code",
   "source": [
    "#画线要注意的是损失是不一定在零到1之间的\n",
    "def plot_learning_curves(record_dict, sample_step=500):\n",
    "    # build DataFrame\n",
    "    train_df = pd.DataFrame(record_dict[\"train\"]).set_index(\"step\").iloc[::sample_step]\n",
    "    val_df = pd.DataFrame(record_dict[\"val\"]).set_index(\"step\")\n",
    "\n",
    "    # plot\n",
    "    fig_num = len(train_df.columns)\n",
    "    fig, axs = plt.subplots(1, fig_num, figsize=(5 * fig_num, 5))\n",
    "    for idx, item in enumerate(train_df.columns):    \n",
    "        axs[idx].plot(train_df.index, train_df[item], label=f\"train_{item}\")\n",
    "        axs[idx].plot(val_df.index, val_df[item], label=f\"val_{item}\")\n",
    "        axs[idx].grid()\n",
    "        axs[idx].legend()\n",
    "        # axs[idx].set_xticks(range(0, train_df.index[-1], 5000))\n",
    "        # axs[idx].set_xticklabels(map(lambda x: f\"{int(x/1000)}k\", range(0, train_df.index[-1], 5000)))\n",
    "        axs[idx].set_xlabel(\"step\")\n",
    "    \n",
    "    plt.show()\n",
    "\n",
    "plot_learning_curves(record, sample_step=100)  #横坐标是 steps"
   ],
   "metadata": {
    "is_executing": true,
    "execution": {
     "iopub.status.busy": "2023-12-06T07:17:50.072257Z",
     "iopub.execute_input": "2023-12-06T07:17:50.072556Z",
     "iopub.status.idle": "2023-12-06T07:17:50.597895Z",
     "shell.execute_reply.started": "2023-12-06T07:17:50.072525Z",
     "shell.execute_reply": "2023-12-06T07:17:50.596991Z"
    },
    "trusted": true
   },
   "execution_count": 32,
   "outputs": [
    {
     "output_type": "display_data",
     "data": {
      "text/plain": "<Figure size 1000x500 with 2 Axes>",
      "image/png": "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TmJiYjjllFP405/+xOjRo0Nu89RTT/H888+zdetWAKZMmcK9997LSSf1nNjQenganG686WNQ9n4MJXIXSBC6FHOseic5DDweDzW1tSQmJGAwdLKy1hwb0epXXHEF119/PY899hhWq5UXXniBH/7whxgMBurq6rjzzjt57733KCoqwuVy0djYSEFB5xsrd+zYwaRJk3SxAzBjxgw8Hg/5+fnMnDmTq6++mjlz5nDOOedw9tln84Mf/ICcnBwAFi9ezE9+8hP+/e9/c/bZZ3PppZfqwkiIAoKcH116HrR37DBp7/y44447ePfddzl69Ginz4+PPvqIZcuWsXPnTmpqanC5XDQ1NdHQ0EBsbCxbtmzh0ksvDbrtjh07sNvtujATBH92H61lUGosNrOxx4/t9XrZXlTDqKwEzMb2z2tNEMSYjaQnWAFocnpocrp7Jf6uRsvw9GY5G0TYw7NmzRoWLlzIpk2bWLlyJU6nk9mzZ1NfXx9ym9WrV3P55ZfzySefsHHjRgYNGsTs2bM5cuRIp4MPF62Hx+sFR5pPnJWKU5sgdCmKopbNhPtjjo1s/VA/SmR3jObPn4/X6+W9997j0KFDrFu3jiuuuAKAW2+9lTfffJN7772XdevWsWXLFiZOnIjD0TN325599lk2btzIKaecwiuvvMKoUaPYtGkTAHfeeSfbtm3jvPPO4+OPP2bcuHG8+eabPRKX0AWEOj+66jzoonOkvfPjrbfe4g9/+ANr1qzp1Plx4MABzj//fI477jj++9//snnzZh599FEAfX8xMTEht2/rOaF/8+63hZzz17U88vGeXjn+RztKOO9v6/n5y1vCWr9ZEJhIsJow+rIgNcdIH4/2OhJtUSR4PvjgA66++mrGjx/PpEmTeO655ygoKGDz5s0ht3nhhRe46aabOP744xkzZgz//Oc/8Xg8rFq1qtPBh4vNZERBbdpsSPKVgUiGRxD6JTabje9///u88MILvPTSS4wePZoTTjgBUBukr776ar73ve8xceJEsrOzOXDgQJccd+zYsXzzzTcBN4g2bNiAwWAIyJJPnjyZJUuW8OmnnzJhwgRefPFF/blRo0bxi1/8ghUrVvD973+fZ599tktiEwSN9s6Pq666ivPPP7/T58fmzZvxeDz85S9/4eSTT2bUqFEUFgZmwI477riQ1wojR44kJiamR68lhOjg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PvtsEhISKC4u5uGHH+5yzIsWLeKMM84gNTWVvLw8rrzySnbt2hW0TEtLC7fddhvZ2dmkpKTw9a9/ncrKyqBlDh06xKWXXkpSUhJ5eXn8/Oc/x+12By1TWlrK6aefjt1uZ/jw4SxZsqTLcS9evJgJEyYYQ6xmzJjBO++806djbsuDDz6Ioij85Cc/6dNx33fffSiKEvQzevToPh2zztGjR/nud79LdnY2iYmJjB8/nnXr1hnP98XvZElJSbv3W1EUbrvtNqBvv99CaHrz2BSPxyWIz2NTfzgugRyb5NjUnrg7Lqn9mJdeekm12Wzqc889p27btk295ZZb1IyMDLWysrLHYli6dKl69913q6+++qoKqK+99lrQ8w8++KCanp6uvv766+qmTZvUr371q+qQIUPU5uZmY5mLLrpInThxovrpp5+qq1evVocPH65ec801xvN1dXVqfn6+eu2116pbt25V//nPf6qJiYnq008/3aWY586dqz7//PPq1q1b1Y0bN6qXXHKJOmjQILWhocFY5tZbb1WLi4vVlStXquvWrVO/8pWvqGeeeabxvNvtVseNG6fOmjVL/eKLL9SlS5eqOTk56l133WUss2/fPjUpKUldsGCBun37dvWPf/yjajab1WXLlnUp7v/+97/q22+/rX755Zfqrl271F/+8peq1WpVt27d2mdjDuSzzz5TS0pK1AkTJqi333678XhfjHvhwoXq2LFj1fLycuOnqqqqT8esqqpaU1OjDh48WL3hhhvUtWvXqvv27VPfffdddc+ePcYyffE7eezYsaD3esWKFSqgfvDBB6qq9t33WwhNbx+b4vG4pKrxeWyK9+OSqsqxSY5NoYm341K/FjzTpk1Tb7vtNuO+x+NRBwwYoC5atKhX4ml7YPF6vWpBQYH6u9/9znistrZWtdvt6j//+U9VVVV1+/btKqB+/vnnxjLvvPOOqiiKevToUVVVVfXJJ59UMzMzVafTaSxzxx13qKNGjeqWuI8dO6YC6ocffmjEaLVa1X/961/GMjt27FABdc2aNaqqagdUk8mkVlRUGMssXrxYTUtLM+L8xS9+oY4dOzZoX1dffbU6d+7cbolbVVU1MzNTffbZZ/t8zPX19eqIESPUFStWqOeee65xUOmrcS9cuFCdOHFiyOf6asyqqn0vZs6cGfb5ePlO3n777eqwYcNUr9fbp99vITR96dgUr8clVY3fY1O8HJdUVY5NPRGzqvaPY1NfPy7125K21tZW1q9fz6xZs4zHTCYTs2bNYs2aNb0YmZ/9+/dTUVERFGN6ejrTp083YlyzZg0ZGRlMnTrVWGbWrFmYTCbWrl1rLHPOOedgs9mMZebOncuuXbs4ceLEScdZV1cHQFZWFgDr16/H5XIFxT169GgGDRoUFPf48ePJz88PisnhcLBt2zZjmcBt6Mt0x+fj8Xh46aWXaGxsZMaMGX0+5ttuu41LL7203bb7cty7d+9mwIABDB06lGuvvZZDhw71+Zj/+9//MnXqVL75zW+Sl5fH5MmTeeaZZ4zn4+E72drayosvvsiNN96Ioih9+v0W2tPXj03x8B3QibdjU7wdl0COTT0Vc7wfm+LhuNRvBU91dTUejyfojQTIz8+noqKil6IKRo+joxgrKirIy8sLet5isZCVlRW0TKhtBO6jq3i9Xn7yk59w1llnMW7cOGObNpuNjIyMDuPuLKZwyzgcDpqbm7sU75YtW0hJScFut3Prrbfy2muvMWbMmD4d80svvcSGDRtYtGhRu+f6atzTp09nyZIlLFu2jMWLF7N//37OPvts6uvr+2zMAPv27WPx4sWMGDGCd999lx/+8If8+Mc/5oUXXgjad1/+Tr7++uvU1tZyww03GNvrq++30J6+fmyKh+8AxNexKR6PSyDHpp6KGeL/2BQPxyVLVEsLpxy33XYbW7du5aOPPurtUCJi1KhRbNy4kbq6Ov79739z/fXX8+GHH/Z2WGE5fPgwt99+OytWrCAhIaG3w4mYiy++2Lg9YcIEpk+fzuDBg3nllVdITEzsxcg6xuv1MnXqVB544AEAJk+ezNatW3nqqae4/vrrezm6yPjLX/7CxRdfzIABA3o7FEHoNeLp2BRvxyWQY1NPE+/Hpng4LvXbDE9OTg5ms7mdI0RlZSUFBQW9FFUwehwdxVhQUMCxY8eCnne73dTU1AQtE2obgfvoCvPnz+ett97igw8+YODAgUFxt7a2Ultb22HcncUUbpm0tLQu/2Oy2WwMHz6cKVOmsGjRIiZOnMjjjz/eZ2Nev349x44d4/TTT8disWCxWPjwww/5wx/+gMViIT8/v0/G3ZaMjAxGjhzJnj17+ux7DVBYWMiYMWOCHjvttNOMkoe+/p08ePAg7733HjfffLPxWF9+v4X29PVjU1//DkD8HZvi7bgEcmzq6Zjj+dgUL8elfit4bDYbU6ZMYeXKlcZjXq+XlStXMmPGjF6MzM+QIUMoKCgIitHhcLB27VojxhkzZlBbW8v69euNZd5//328Xi/Tp083llm1ahUul8tYZsWKFYwaNYrMzMyo41JVlfnz5/Paa6/x/vvvM2TIkKDnp0yZgtVqDYp7165dHDp0KCjuLVu2BH35VqxYQVpamvGlnjFjRtA29GW68/Pxer04nc4+G/OFF17Ili1b2Lhxo/EzdepUrr32WuN2X4y7LQ0NDezdu5fCwsI++14DnHXWWe1sbL/88ksGDx4M9N3vpM7zzz9PXl4el156qfFYX36/hfb09WNTX/4O9JdjU18/LoEcm+TYFDlxc1yK3ochfnjppZdUu92uLlmyRN2+fbv6/e9/X83IyAhyhIg19fX16hdffKF+8cUXKqA++uij6hdffKEePHhQVVXNZjAjI0N944031M2bN6tXXHFFSJvByZMnq2vXrlU/+ugjdcSIEUE2g7W1tWp+fr76ve99T926dav60ksvqUlJSV22//zhD3+opqenq6WlpUGWg01NTcYyt956qzpo0CD1/fffV9etW6fOmDFDnTFjhvG8bjc4Z84cdePGjeqyZcvU3NzckHaDP//5z9UdO3aoTzzxxElZO955553qhx9+qO7fv1/dvHmzeuedd6qKoqjLly/vszGHItAJp6/G/b//+79qaWmpun//fvXjjz9WZ82apebk5KjHjh3rszGrqmavarFY1N/+9rfq7t271b///e9qUlKS+uKLLxrL9MXvpKpqTl6DBg1S77jjjnbP9dX3WwhNbx+b4vG4pKrxeWzqL8clVZVjU6xiVtX4PTbF03GpXwseVVXVP/7xj+qgQYNUm82mTps2Tf300097dP8ffPCBCrT7uf7661VV1awG77nnHjU/P1+12+3qhRdeqO7atStoG8ePH1evueYaNSUlRU1LS1PnzZun1tfXBy2zadMmdebMmardbleLiorUBx98sMsxh4oXUJ9//nljmebmZvVHP/qRmpmZqSYlJalXXXWVWl5eHrSdAwcOqBdffLGamJio5uTkqP/7v/+rulyudu/PpEmTVJvNpg4dOjRoH9Fy4403qoMHD1ZtZ/ky2QAABO5JREFUNpuam5urXnjhhcZBpa/GHIq2B5W+GPfVV1+tFhYWqjabTS0qKlKvvvrqoHkBfTFmnTfffFMdN26carfb1dGjR6t//vOfg57vi99JVVXVd999VwXaxaKqffv9FkLTm8emeDwuqWp8Hpv6y3FJVeXYFKuYdeLx2BRPxyVFVVU1+ryQIAiCIAiCIAhC36ff9vAIgiAIgiAIgiCI4BEEQRAEQRAEod8igkcQBEEQBEEQhH6LCB5BEARBEARBEPotIngEQRAEQRAEQei3iOARBEEQBEEQBKHfIoJHEARBEARBEIR+iwgeQRAEQRAEQRD6LSJ4BKGbuOGGG7jyyit7OwxBEARBAOS4JAg6IngEQRAEQRAEQei3iOARhCj597//zfjx40lMTCQ7O5tZs2bx85//nBdeeIE33ngDRVFQFIXS0lIADh8+zLe+9S0yMjLIysriiiuu4MCBA8b29Ctw999/P7m5uaSlpXHrrbfS2traOy9QEARBiCvkuCQIHWPp7QAEIZ4oLy/nmmuu4eGHH+aqq66ivr6e1atXc91113Ho0CEcDgfPP/88AFlZWbhcLubOncuMGTNYvXo1FouF3/zmN1x00UVs3rwZm80GwMqVK0lISKC0tJQDBw4wb948srOz+e1vf9ubL1cQBEHo48hxSRA6RwSPIERBeXk5brebr33tawwePBiA8ePHA5CYmIjT6aSgoMBY/sUXX8Tr9fLss8+iKAoAzz//PBkZGZSWljJnzhwAbDYbzz33HElJSYwdO5b/9//+Hz//+c/59a9/jckkiVhBEAQhNHJcEoTOkb9YQYiCiRMncuGFFzJ+/Hi++c1v8swzz3DixImwy2/atIk9e/aQmppKSkoKKSkpZGVl0dLSwt69e4O2m5SUZNyfMWMGDQ0NHD58OKavRxAEQYhv5LgkCJ0jGR5BiAKz2cyKFSv45JNPWL58OX/84x+5++67Wbt2bcjlGxoamDJlCn//+9/bPZebmxvrcAVBEIR+jhyXBKFzRPAIQpQoisJZZ53FWWedxb333svgwYN57bXXsNlseDyeoGVPP/10Xn75ZfLy8khLSwu7zU2bNtHc3ExiYiIAn376KSkpKRQXF8f0tQiCIAjxjxyXBKFjpKRNEKJg7dq1PPDAA6xbt45Dhw7x6quvUlVVxWmnnUZJSQmbN29m165dVFdX43K5uPbaa8nJyeGKK65g9erV7N+/n9LSUn784x9z5MgRY7utra3cdNNNbN++naVLl7Jw4ULmz58vddKCIAhCh8hxSRA6RzI8ghAFaWlprFq1isceewyHw8HgwYP5/e9/z8UXX8zUqVMpLS1l6tSpNDQ08MEHH3DeeeexatUq7rjjDr72ta9RX19PUVERF154YdCVtQsvvJARI0Zwzjnn4HQ6ueaaa7jvvvt674UKgiAIcYEclwShcxRVVdXeDkIQTmVuuOEGamtref3113s7FEEQBEGQ45LQ75C8pCAIgiAIgiAI/RYRPIIgCIIgCIIg9FukpE0QBEEQBEEQhH6LZHgEQRAEQRAEQei3iOARBEEQBEEQBKHfIoJHEARBEARBEIR+iwgeQRAEQRAEQRD6LSJ4BEEQBEEQBEHot4jgEQRBEARBEASh3yKCRxAEQRAEQRCEfosIHkEQBEEQBEEQ+i0ieARBEARBEARB6Lf8f05PqSNi5FNdAAAAAElFTkSuQmCC"
     },
     "metadata": {}
    }
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "# 评估"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "source": [
    "# dataload for evaluating\n",
    "\n",
    "# load checkpoints\n",
    "model.load_state_dict(torch.load(\"checkpoints/vgg/best.ckpt\", map_location=\"cpu\"))\n",
    "\n",
    "model.eval()\n",
    "loss, acc = evaluating(model, eval_dl, loss_fct)\n",
    "print(f\"loss:     {loss:.4f}\\naccuracy: {acc:.4f}\")"
   ],
   "metadata": {
    "is_executing": true,
    "execution": {
     "iopub.status.busy": "2023-12-06T07:17:50.599051Z",
     "iopub.execute_input": "2023-12-06T07:17:50.599860Z",
     "iopub.status.idle": "2023-12-06T07:17:52.535945Z",
     "shell.execute_reply.started": "2023-12-06T07:17:50.599823Z",
     "shell.execute_reply": "2023-12-06T07:17:52.534902Z"
    },
    "trusted": true
   },
   "execution_count": 33,
   "outputs": [
    {
     "name": "stdout",
     "text": "loss:     0.8707\naccuracy: 0.6976\n",
     "output_type": "stream"
    }
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "# 推理"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "source": [
    "# # test_df\n",
    "# test_ds = Cifar10Dataset(\"test\", transform=transforms_eval)\n",
    "# test_dl = DataLoader(test_ds, batch_size=batch_size, shuffle=False, drop_last=False)\n",
    "#\n",
    "# preds_collect = []\n",
    "# model.eval()\n",
    "# for data, fake_label in tqdm(test_dl):\n",
    "#     data = data.to(device=device)\n",
    "#     logits = model(data)\n",
    "#     preds = [test_ds.idx_to_label[idx] for idx in logits.argmax(axis=-1).cpu().tolist()]\n",
    "#     preds_collect.extend(preds)\n",
    "#\n",
    "# test_df[\"class\"] = preds_collect\n",
    "# test_df.head()"
   ],
   "metadata": {
    "is_executing": true,
    "execution": {
     "iopub.status.busy": "2023-12-06T07:17:52.537520Z",
     "iopub.execute_input": "2023-12-06T07:17:52.537874Z",
     "iopub.status.idle": "2023-12-06T07:17:52.542629Z",
     "shell.execute_reply.started": "2023-12-06T07:17:52.537842Z",
     "shell.execute_reply": "2023-12-06T07:17:52.541721Z"
    },
    "trusted": true
   },
   "execution_count": 34,
   "outputs": []
  },
  {
   "cell_type": "code",
   "source": [
    "# # 导出 submission.csv\n",
    "# test_df.to_csv(\"submission.csv\", index=False)"
   ],
   "metadata": {
    "is_executing": true,
    "execution": {
     "iopub.status.busy": "2023-12-06T07:17:52.544104Z",
     "iopub.execute_input": "2023-12-06T07:17:52.544403Z",
     "iopub.status.idle": "2023-12-06T07:17:52.553761Z",
     "shell.execute_reply.started": "2023-12-06T07:17:52.544379Z",
     "shell.execute_reply": "2023-12-06T07:17:52.552949Z"
    },
    "trusted": true
   },
   "execution_count": 35,
   "outputs": []
  }
 ]
}
